package com.pioneer.web.purchase.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pioneer.common.exception.CustomException;
import com.pioneer.common.utils.SecurityUtils;
import com.pioneer.web.purchase.domain.PurPlan;
import com.pioneer.web.purchase.domain.PurPlanBody;
import com.pioneer.web.purchase.mapper.PurPlanBodyMapper;
import com.pioneer.web.purchase.mapper.PurPlanMapper;
import com.pioneer.web.purchase.service.IPurOrderService;
import com.pioneer.web.purchase.service.IPurPlanService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * PurPlanServiceImpl
 *
 * @author hlm
 * @date 2025-03-25 09:07:59
 */
@Service
public class PurPlanServiceImpl extends ServiceImpl<PurPlanMapper, PurPlan> implements IPurPlanService {

    @Resource
    private PurPlanBodyMapper planBodyMapper;

    @Resource
    private IPurOrderService orderService;

    @Override
    public PurPlan selectPlanById(Long planId) {
        // 根据采购计划ID查询采购计划
        PurPlan plan = getById(planId);
        // 校验采购计划单
        if (plan == null) {
            throw new CustomException("采购计划单不存在，请刷新后重试");
        }
        // 根据采购计划ID查询采购计划子信息
        LambdaQueryWrapper<PurPlanBody> query = Wrappers.lambdaQuery();
        query.eq(PurPlanBody::getPlanId, planId);
        List<PurPlanBody> planBodyList = planBodyMapper.selectList(query);
        plan.setPlanBodyList(planBodyList);
        return plan;
    }

    @Override
    public int addPlan(PurPlan plan) {
        // 校验采购计划单子表信息
        List<PurPlanBody> planBodyList = plan.getPlanBodyList();
        if (CollUtil.isEmpty(planBodyList)) {
            throw new CustomException("采购计划单子表信息不能为空");
        }
        // 处理数据
        PurPlan addPlan = dealData(plan);
        // 保存采购计划
        save(addPlan);
        // 采购计划子信息设置采购计划ID
        planBodyList = planBodyList.stream().peek(planBody -> planBody.setPlanId(addPlan.getPlanId())).toList();
        // 批量保存采购计划子信息
        return planBodyMapper.insertBatch(planBodyList);
    }

    @Override
    public int editPlan(PurPlan plan) {
        PurPlan purPlan = getById(plan.getPlanId());
        // 校验采购计划单
        if (purPlan == null) {
            throw new CustomException("采购计划单不存在，请刷新后重试");
        }
        // 校验采购计划单子表信息
        List<PurPlanBody> planBodyList = plan.getPlanBodyList();
        if (CollUtil.isEmpty(planBodyList)) {
            throw new CustomException("采购计划单子表信息不能为空");
        }
        // 校验计划状态
        if (!"0".equals(purPlan.getApproveStatus())) {
            throw new CustomException("只有计划状态为初始的数据才可以修改");
        }
        // 处理数据
        PurPlan editPlan = dealData(plan);
        // 修改采购计划
        updateById(editPlan);
        // 修改采购计划子信息
        planBodyMapper.deleteBodyById(Collections.singletonList(plan.getPlanId()));
        // 采购计划子信息设置采购计划ID
        planBodyList = planBodyList.stream().peek(planBody -> planBody.setPlanId(editPlan.getPlanId())).toList();
        // 批量保存采购计划子信息
        return planBodyMapper.insertBatch(planBodyList);
    }

    @Override
    public boolean deletePlans(List<Long> list) {
        // 根据采购计划ID集合查询数据
        List<PurPlan> purPlanList = getBaseMapper().selectBatchIds(list);
        // 校验计划状态
        for (PurPlan purPlan : purPlanList) {
            if (!"0".equals(purPlan.getApproveStatus())) {
                throw new CustomException("只有计划状态为初始的数据才可以修改");
            }
        }
        // 根据采购计划ID集合删除子信息
        planBodyMapper.deleteBodyById(list);
        // 删除采购计划
        return removeByIds(list);
    }

    @Override
    public boolean commitPlan(PurPlan plan) {
        PurPlan purPlan = getById(plan.getPlanId());
        if (purPlan == null) {
            throw new CustomException("采购计划单不存在，请刷新后重试");
        }
        if (!"0".equals(purPlan.getApproveStatus())) {
            throw new CustomException("只有计划状态为初始的数据才可以提交");
        }
        PurPlan commitPlan = new PurPlan();
        commitPlan.setPlanId(plan.getPlanId());
        commitPlan.setApproveStatus("1");
        return updateById(commitPlan);
    }

    @Override
    public boolean recallPlan(PurPlan plan) {
        PurPlan purPlan = getById(plan.getPlanId());
        if (purPlan == null) {
            throw new CustomException("采购计划单不存在，请刷新后重试");
        }
        if (!"1".equals(purPlan.getApproveStatus())) {
            throw new CustomException("只有计划状态为审批中的数据才可以撤回");
        }
        PurPlan commitPlan = new PurPlan();
        commitPlan.setPlanId(plan.getPlanId());
        commitPlan.setApproveStatus("0");
        return updateById(commitPlan);
    }

    @Override
    public boolean approvePlan(PurPlan plan) {
        PurPlan purPlan = selectPlanById(plan.getPlanId());
        if (purPlan == null) {
            throw new CustomException("采购计划单不存在，请刷新后重试");
        }
        if (!"1".equals(purPlan.getApproveStatus())) {
            throw new CustomException("只有计划状态为初始的数据才可以审批");
        }
        PurPlan approvePlan = new PurPlan();
        approvePlan.setPlanId(plan.getPlanId());
        approvePlan.setApprover(SecurityUtils.getLoginUser().getUsername());
        approvePlan.setApproveTime(LocalDateTime.now());
        approvePlan.setApproveOpinion(plan.getApproveOpinion());
        String approveResult = plan.getApproveResult();
        if (StrUtil.isBlank(approveResult)) {
            throw new CustomException("审批结果不能为空，请选择");
        }
        switch (approveResult) {
            case "pass" -> {
                // 将计划状态改为审批通过
                approvePlan.setApproveStatus("2");
                // 自动生成一张采购订单
                String msg = orderService.genOrderByPlan(purPlan);
                if (msg != null) {
                    throw new CustomException(msg);
                }
            }
            case "notPass" -> {
                // 校验审批意见
                String approveOpinion = plan.getApproveOpinion();
                if (StrUtil.isBlank(approveOpinion)) {
                    throw new CustomException("审批意见不能为空");
                }
                // 将计划状态改为审批不通过
                approvePlan.setApproveStatus("3");
            }
            case "reject" -> {
                // 校验审批意见
                String approveOpinion = plan.getApproveOpinion();
                if (StrUtil.isBlank(approveOpinion)) {
                    throw new CustomException("审批意见不能为空");
                }
                // 将计划状态改为初始
                approvePlan.setApproveStatus("0");
            }
        }
        return updateById(approvePlan);
    }

    @Override
    public boolean unapprovePlan(PurPlan plan) {
        PurPlan purPlan = selectPlanById(plan.getPlanId());
        if (purPlan == null) {
            throw new CustomException("采购计划单不存在，请刷新后重试");
        }
        if (!"2".equals(purPlan.getApproveStatus()) && !"3".equals(purPlan.getApproveStatus())) {
            throw new CustomException("只有计划状态为审批通过/不通过的数据才可以弃审");
        }
        // 删除下游单据
        String msg = orderService.delOrderByPlan(purPlan);
        if (msg != null) {
            throw new CustomException(msg);
        }
        // 弃审
        PurPlan approvePlan = new PurPlan();
        approvePlan.setPlanId(plan.getPlanId());
        approvePlan.setApprover(null);
        approvePlan.setApproveTime(null);
        approvePlan.setApproveOpinion(null);
        approvePlan.setApproveStatus("1");
        return updateById(approvePlan);
    }

    /**
     * 处理数据
     * @param plan 采购计划
     * @return 结果
     */
    private PurPlan dealData(PurPlan plan) {
        List<PurPlanBody> planBodyList = plan.getPlanBodyList();
        // 计算总额
        BigDecimal total = BigDecimal.ZERO;
        for (int i = 0; i < planBodyList.size(); i++) {
            PurPlanBody planBody = planBodyList.get(i);
            if (ObjectUtil.isNull(planBody.getDeptId())) {
                throw new CustomException("第" + (i + 1) + "行采购部门不能为空");
            }
            if (ObjectUtil.isNull(planBody.getInventoryId())) {
                throw new CustomException("第" + (i + 1) + "行存货管理不能为空");
            }
            BigDecimal planPurNumber = planBody.getPlanPurNumber();
            if (planPurNumber == null || planPurNumber.doubleValue() <= 0) {
                throw new CustomException("第" + (i + 1) + "行计划采购数量必须大于0");
            }
            BigDecimal planPrice = planBody.getPlanPrice();
            if (planPrice == null || planPrice.doubleValue() < 0) {
                throw new CustomException("第" + (i + 1) + "行计划采购单价必须大于等于0");
            }
            // 计算每一行的总价
            planBody.setPlanTotal(planBody.getPlanPurNumber().multiply(planBody.getPlanPrice()));
            // 计算单据总额
            total = total.add(planBody.getPlanTotal());
        }
        PurPlan dealPlan = new PurPlan();
        if (ObjectUtil.isNull(plan.getPlanId())) {
            // 设置计划编号
            dealPlan.setPlanCode(genPlanCode());
            // 设置采购计划名称
            dealPlan.setPlanName(plan.getPlanName());
            // 设置计划状态
            dealPlan.setApproveStatus("0");
            // 设置总额
            dealPlan.setTotal(total);
        } else {
            // 设置采购计划ID
            dealPlan.setPlanId(plan.getPlanId());
            // 设置采购计划名称
            dealPlan.setPlanName(plan.getPlanName());
            // 设置总额
            dealPlan.setTotal(total);
        }
        return dealPlan;
    }

    /**
     * 生成采购计划编号：PLAN+日期+3位流水
     * @return 结果
     */
    private String genPlanCode() {
        // 根据指定格式获取当天字符串
        String today = DateUtil.format(new Date(), "yyyyMMdd");
        // 查询当天最大流水号记录
        String maxCode = getBaseMapper().selectMaxCode(today);
        if (StrUtil.isBlank(maxCode)) {
            // 当天没有流水号，直接返回
            return "PLAN" + today + "001";
        } else {
            // 截取最后三位
            String oldCode = maxCode.substring(maxCode.length() - 3);
            // 流水号+1并补0
            String newCode = String.format("%03d", Integer.parseInt(oldCode) + 1);
            // 返回新的流水号
            return "PLAN" + today + newCode;
        }
    }
}
